package org.gd.hellojaxb.privat24.utils;

import org.gd.hellojaxb.privat24.utils.connection.HttpTimeoutHandler;

import javax.net.ssl.*;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
import java.security.KeyStore;
import java.security.SecureRandom;
import java.security.cert.X509Certificate;

public class Http {

    public static String sslQuery(String host, String getStr) {
        String keystpatch = "/sybase/rsn/keys/privat24-client.jks";
        String keystpass = "vsirfysy";
        StringBuffer sb = null;
        BufferedReader br = null;
        OutputStreamWriter out = null;
        try {
            // Получить экземпляр хранилища ключей.
            KeyStore keyStore = KeyStore.getInstance("JKS");
            FileInputStream fis = new FileInputStream(keystpatch);
            keyStore.load(fis, keystpass.toCharArray());

            // Получить диспетчеры ключей базовой реализации для заданного хранилища ключей.
            KeyManagerFactory keyManagerFactory = KeyManagerFactory.getInstance("IbmX509");
            keyManagerFactory.init(keyStore, keystpass.toCharArray());
            KeyManager[] keyManagers = keyManagerFactory.getKeyManagers();

            // Получить доверенные диспетчеры базовой реализации.
            TrustManagerFactory trustManagerFactory = TrustManagerFactory.getInstance("IbmX509");
            trustManagerFactory.init(keyStore);
            TrustManager[] trustManagers = trustManagerFactory.getTrustManagers();

            // Получить защищенное случайное число.
            SecureRandom secureRandom = SecureRandom.getInstance("SHA1PRNG");

            // Создание SSL контекста
            SSLContext sslContext = SSLContext.getInstance("SSLv3");
            sslContext.init(keyManagers, trustManagers, secureRandom);

            // Создание фабрики SSL сокетов.
            javax.net.ssl.SSLSocketFactory sslSocketFactory = sslContext.getSocketFactory();

            // Создаем сокет.
            SSLSocket sslClientSocket = (SSLSocket) sslSocketFactory.createSocket(host, 443);

            out = new OutputStreamWriter(sslClientSocket.getOutputStream());
            out.write("GET / HTTP/1.0\\r\\n");
            out.write(getStr + "\\r\\n");
            out.flush();

            System.err.println("request sended!"); /////////

            br = new BufferedReader(new InputStreamReader(sslClientSocket.getInputStream()));

            String nextLine = null;
            sb = new StringBuffer();
            while ((nextLine = br.readLine()) != null) {
                System.err.println("responce line: " + nextLine); ///////////
                sb.append(nextLine).append("\n");
            }
        } catch (Exception ex) {
            ex.printStackTrace();
        } finally {
            try {
                out.close();
                br.close();
            } catch (IOException ex) {
            }
        }
        return sb.toString();
    }

//    public static String soapS(String urlString, String request) throws Exception {
//      return soap(urlString, "text/xml", request, true);
//    }

    public static String soap(String urlString, String request) throws Exception {
        return soap(urlString, "text/xml", request);

    }

    public static void soap(String urlString) throws Exception {
        URL url = new URL(urlString);
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if (conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {

                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        }

        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);
        conn.setInstanceFollowRedirects(false);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod("POST");

        Writer wout = new OutputStreamWriter(conn.getOutputStream());
        wout.flush();
        wout.close();
    }
    public static String soap(String urlString, String conttype, String request, boolean ignoreSSL) throws Exception {
        if(ignoreSSL) {
            try{
                SSLContext context = SSLContext.getInstance("SSLv3");
                TrustManager[] trustManagerArray = { new NullX509TrustManager() };
                context.init(null, trustManagerArray, null);
                HttpsURLConnection.setDefaultSSLSocketFactory(context.getSocketFactory());
                HttpsURLConnection.setDefaultHostnameVerifier(new NullHostnameVerifier());
            }catch(Exception e) {
                e.printStackTrace();
            }
        }
        return soap(urlString, conttype, request);
    }
    public static String soap(String urlString, String conttype, String request) throws Exception {
        System.err.println("0.0");
        URL url = new URL(urlString);
        long start = System.currentTimeMillis();
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if (conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {

                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        }

        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);
        conn.setInstanceFollowRedirects(false);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-type", conttype);
        //conn.setConnectTimeout(30000);
        //Thread.sleep(5000);

        Writer wout = new OutputStreamWriter(conn.getOutputStream());
        wout.write(request);
        wout.flush();
        wout.close();

        long time = System.currentTimeMillis() - start;
        System.err.println("---CHECK_REQUEST");
        System.err.println("---URL: " + urlString);
        System.err.println("---TIME: " + time + " ms");

        //conn.connect();

        // conn.getHeaderField(null);
        System.err.println("1.1");
        System.err.println("HTTP.soap-->req:" + request + " code:" + conn.getResponseCode());
        if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAVAILABLE) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Сервис недоступен</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Ресурс не найден</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Неправильный запрос</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_METHOD) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Метод не разрешен для данного ресурса</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Ошибка в работе ресурса</error>";
        }
        System.err.println("2.2");
        if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
            return "";
        }

        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String nextLine = null;
        StringBuilder sb = new StringBuilder();
        while ((nextLine = in.readLine()) != null) {
            sb.append(nextLine).append("\n");
        }

        return sb.toString();
    }

    public static String soapTimeout(String urlString, String conttype, String request, int timeout) throws Exception {
        //URL url = new URL(urlString);
        URL url = new URL((URL) null, urlString, new HttpTimeoutHandler(timeout));
        System.err.println("timeout: " + timeout);

        //url.setURLStreamHandlerFactory(new HttpTimeoutFactory(timeout));
        long start = System.currentTimeMillis();

        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if (conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {

                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        }

        conn.setUseCaches(false);
        conn.setAllowUserInteraction(false);
        conn.setInstanceFollowRedirects(false);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod("POST");
        conn.setRequestProperty("Content-type", conttype);

        Writer wout = new OutputStreamWriter(conn.getOutputStream());
        wout.write(request);
        wout.flush();
        wout.close();
        long time = System.currentTimeMillis() - start;
        System.err.println("---CHECK_REQUEST");
        System.err.println("---URL: " + urlString);
        System.err.println("---TIME: " + time + " ms");

        //conn.connect();

        // conn.getHeaderField(null);
        if (conn.getResponseCode() == HttpURLConnection.HTTP_UNAVAILABLE) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Сервис временно не доступен, попробуйте еще раз или повторите операцию позже</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_NOT_FOUND) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Ресурс не найден</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_REQUEST) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Неправильный запрос</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_BAD_METHOD) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Метод не разрешен для данного ресурса</error>";
        } else if (conn.getResponseCode() == HttpURLConnection.HTTP_INTERNAL_ERROR) {
            return "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><error>Ошибка в работе ресурса</error>";
        }
        if ((conn.getResponseCode() != HttpURLConnection.HTTP_OK) && (conn.getResponseCode() != HttpURLConnection.HTTP_CREATED)) {
            return "";
        }

        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
        String nextLine = null;
        StringBuilder sb = new StringBuilder();
        while ((nextLine = in.readLine()) != null) {
            sb.append(nextLine).append("\n");
        }
        return sb.toString();
    }

    public static String soap(String urlString, String request, boolean IgnoreSSL) throws Exception {
        return soap(urlString, request, IgnoreSSL, null);
    }

    public static String soap(String urlString, String request, boolean IgnoreSSL, String coding) throws Exception {
        URL url = new URL(urlString);
        StringBuilder sb = new StringBuilder();
        if (IgnoreSSL) {
            // Create a trust manager that does not validate certificate chains like the default TrustManager
            // This routine right is what Netscape and IE do when they receive a certificate that is not their
            // KeyStore. The only difference is that this code does not ask you to accept it.
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};
            try {
                // Let us create the factory where we can set some parameters for the connection
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new SecureRandom());

                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            } catch (java.security.NoSuchAlgorithmException nsae) {
                System.err.println("\n" + "The context specified does not exist. Check for the existence of JSSE" + "\n");
                System.err.println(nsae.getMessage());
                //System.exit(-1);

            } catch (java.security.KeyManagementException kme) {
                kme.printStackTrace();
                System.err.println(kme.getMessage());
                //System.exit(-1);
            }

        }

        try {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            if (conn instanceof HttpsURLConnection) {
                ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {

                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
            }

            conn.setUseCaches(false);
            conn.setAllowUserInteraction(false);
            conn.setInstanceFollowRedirects(false);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-type", "text/xml");

            Writer wout = new OutputStreamWriter(conn.getOutputStream());
            wout.write(request);
            wout.flush();
            wout.close();

            //conn.connect();

            // conn.getHeaderField(null);

            if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "";
            }
            BufferedReader in = null;
            if (coding == null) {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            } else {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), coding));
            }
            String nextLine = "";
            while ((nextLine = in.readLine()) != null) {
                sb.append(nextLine).append("\n");
            }
            in.close();

        } catch (MalformedURLException mue) {
            System.err.println("\n" + "URL is not exist or protocol does not exist or there is a typo in the submitted URL" + "\n");
            System.err.println(mue.getMessage());
            //System.exit(-1);

        } catch (java.net.UnknownHostException uhe) {
            System.err.println("\n" + "Remote server does not exist in DNS." + "\n");
            System.err.println(uhe.getMessage());
            //System.exit(-1);

        } catch (IOException ioe) {
            System.err.println("\n" + "I/O Exception in the connection try again or contact developer." + "\n");
            System.err.println(ioe.getMessage());
            ioe.printStackTrace();
            //System.exit(-1);
        }
        return sb.toString();
    }


    public static String soap(String urlString, String request, boolean IgnoreSSL, String coding, String ErrorMessage, int connectTimeout, int readTimeout) throws Exception {

        long start = System.currentTimeMillis();
        System.err.println("external request:"+request+" to url:"+urlString+" encoding:"+coding+" sended");

        URL url = new URL(urlString);
        StringBuilder sb = new StringBuilder();
        if (IgnoreSSL) {
            TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {

                public X509Certificate[] getAcceptedIssuers() {
                    return null;
                }

                public void checkClientTrusted(X509Certificate[] certs, String authType) {
                }

                public void checkServerTrusted(X509Certificate[] certs, String authType) {
                }
            }};
            try {
                // Let us create the factory where we can set some parameters for the connection
                SSLContext sc = SSLContext.getInstance("SSL");
                sc.init(null, trustAllCerts, new SecureRandom());

                HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

            } catch (java.security.NoSuchAlgorithmException nsae) {
                System.err.println("\n" + "The context specified does not exist. Check for the existence of JSSE" + "\n");
                System.err.println(nsae.getMessage());
            } catch (java.security.KeyManagementException kme) {
                kme.printStackTrace(System.err);
                System.err.println(kme.getMessage());
            }
        }

        try {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();

            conn.setConnectTimeout(connectTimeout*1000);
            conn.setReadTimeout(readTimeout*1000);

            if (conn instanceof HttpsURLConnection) {
                ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {

                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
            }

            conn.setUseCaches(false);
            conn.setAllowUserInteraction(false);
            conn.setInstanceFollowRedirects(false);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-type", "text/xml");

            Writer wout = new OutputStreamWriter(conn.getOutputStream());
            wout.write(request);
            wout.flush();
            wout.close();

            long time = System.currentTimeMillis() - start;
            System.err.println("external responce code:"+conn.getResponseCode()+" from url:"+urlString+" get at:"+time+" ms");

            if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "";
            }
            BufferedReader in = null;
            if (coding == null) {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream()));
            } else {
                in = new BufferedReader(new InputStreamReader(conn.getInputStream(), coding));
            }
            String nextLine = "";
            while ((nextLine = in.readLine()) != null) {
                sb.append(nextLine).append("\n");
            }
            in.close();

        } catch (MalformedURLException mue) {
            System.err.println("\n" + "URL is not exist or protocol does not exist or there is a typo in the submitted URL" + "\n");
            System.err.println(mue.getMessage());
        } catch (java.net.UnknownHostException uhe) {
            System.err.println("\n" + "Remote server does not exist in DNS." + "\n");
            System.err.println(uhe.getMessage());
        } catch (IOException ioe) {
            if (!ErrorMessage.equals("")) {
                System.err.println(ErrorMessage);
                System.err.println("NMSTAT IQ TIMEOUT REQUEST: " + request);
            }
            System.err.println(ioe.getMessage());
            System.err.println("\n" + "I/O Exception in the connection try again or contact developer." + "\n");
            if(!ErrorMessage.isEmpty()) ioe.printStackTrace(System.err);
        }

        System.err.println("external responce :"+sb.toString()+" from url:"+urlString);
        return sb.toString();
    }

    public static String Request(String requestURL) throws Exception {
        return Request(requestURL, "GET", "");
    }

    public static String Request(String requestURL, String METHOD) throws Exception {
        return Request(requestURL, METHOD, "");
    }

    public static String Request(String requestURL, String METHOD, String data) throws Exception {
        return Request(requestURL, METHOD, data, "KOI8_R");
    }

    public static String Request(String requestURL, String METHOD, String data, String inputEncoding) throws Exception {
        URL url = new URL(requestURL);
        StringBuilder sb = new StringBuilder();
        TrustManager[] trustAllCerts = new TrustManager[]{new X509TrustManager() {
            public X509Certificate[] getAcceptedIssuers() {return null;}
            public void checkClientTrusted(X509Certificate[] certs, String authType) {}
            public void checkServerTrusted(X509Certificate[] certs, String authType) {}
        }};
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());
            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());
        } catch (java.security.NoSuchAlgorithmException nsae) {
            nsae.printStackTrace();
        } catch (java.security.KeyManagementException kme) {
            kme.printStackTrace();
        }
        try {
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            if (conn instanceof HttpsURLConnection) {
                ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {
                    public boolean verify(String hostname, SSLSession session) {
                        return true;
                    }
                });
            }
            conn.setUseCaches(false);
            conn.setDoOutput(true);
            conn.setDoInput(true);
            conn.setRequestMethod(METHOD);
            if ("POST".equals(METHOD)) {
                Writer wout = new OutputStreamWriter(conn.getOutputStream());
                wout.write(data);
                wout.flush();
                wout.close();
            }
            //conn.setRequestProperty("accept", "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8");
            if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
                return "";
            }
            BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), inputEncoding));
            String nextLine = null;
            while ((nextLine = in.readLine()) != null) {
                sb.append(nextLine).append("\n");
            }
        } catch (MalformedURLException mue) {
            mue.printStackTrace();
        } catch (java.net.UnknownHostException uhe) {
            uhe.printStackTrace();
        } catch (IOException ioe) {
            ioe.printStackTrace();
        }
        return sb.toString();
    }

    public static String sendCurl(String url, String request) {
        StringBuilder resp = new StringBuilder();
        try {
            String[] cmdarray = {
                    "curl"," -k", "-d", request, "--connect-timeout", "50", "-m", "50", url
            };
            String command = "curl -k -d " + request + " --connect-timeout 50 -m 50 "+ url;
            System.err.println("http: curl request--->"+command);
            Process pr = Runtime.getRuntime().exec(command);
            String line = null;
            BufferedReader input = new BufferedReader(new InputStreamReader(pr.getInputStream()));
            while ((line = input.readLine()) != null) {
                if (line != null) {
                    resp.append(line);
                }
            }
            input.close();
            pr.waitFor();
            System.out.println("http: curl request exitval--->"+pr.exitValue());
        } catch (Exception e) {
            e.printStackTrace();
        }
        return resp.toString();
    }


    public static String RequestTimeout(String requestURL, String METHOD, String data, String inputEncoding, int connTimeout, int readTimeout) throws MalformedURLException, IOException /*throws Exception*/ {
        URL url = new URL(requestURL);
        StringBuilder sb = new StringBuilder();
        TrustManager[] trustAllCerts = new TrustManager[]{
                new X509TrustManager() {

                    public X509Certificate[] getAcceptedIssuers() {
                        return null;
                    }

                    public void checkClientTrusted(X509Certificate[] certs, String authType) {
                    }

                    public void checkServerTrusted(X509Certificate[] certs, String authType) {
                    }
                }
        };
        try {
            SSLContext sc = SSLContext.getInstance("SSL");
            sc.init(null, trustAllCerts, new SecureRandom());

            HttpsURLConnection.setDefaultSSLSocketFactory(sc.getSocketFactory());

        } catch (java.security.NoSuchAlgorithmException nsae) {
            System.err.println("\n" + "The context specified does not exist. Check for the existence of JSSE" + "\n");
            System.err.println(nsae.getMessage());

        } catch (java.security.KeyManagementException kme) {
            kme.printStackTrace();
            System.err.println(kme.getMessage());
        }
//        try {
        HttpURLConnection conn = (HttpURLConnection) url.openConnection();
        if (conn instanceof HttpsURLConnection) {
            ((HttpsURLConnection) conn).setHostnameVerifier(new HostnameVerifier() {

                public boolean verify(String hostname, SSLSession session) {
                    return true;
                }
            });
        }

        conn.setUseCaches(false);
        conn.setDoOutput(true);
        conn.setDoInput(true);
        conn.setRequestMethod(METHOD);
        conn.setConnectTimeout(connTimeout*1000);
        conn.setReadTimeout(readTimeout*1000);

        if ("POST".equals(METHOD)) {
            Writer wout = new OutputStreamWriter(conn.getOutputStream());
            wout.write(data);
            wout.flush();
            wout.close();
        }


//            if (conn.getResponseCode() != HttpURLConnection.HTTP_OK) {
//                return "";
//            }

        BufferedReader in = new BufferedReader(new InputStreamReader(conn.getInputStream(), inputEncoding));
        String nextLine = null;
        while ((nextLine = in.readLine()) != null) {
            sb.append(nextLine).append("\n");
            System.err.println("wu_resp: "+nextLine);
        }
//        } catch (java.net.MalformedURLException mue) {
//            System.err.println("\n" + "URL is not exist or protocol does not exist or there is a typo in the submitted URL" + "\n");
//            System.err.println(mue.getMessage());
//        } catch (java.net.UnknownHostException uhe) {
//            System.err.println("\n" + "Remote server does not exist in DNS." + "\n");
//            System.err.println(uhe.getMessage());
//        } catch (java.io.IOException ioe) {
//            System.err.println("\n" + "I/O Exception in the connection try again or contact developer." + "\n");
//            System.err.println(ioe.getMessage());
//            ioe.printStackTrace();
//        }
        return sb.toString();
    }


    public static class NullX509TrustManager implements X509TrustManager { /* Implements all methods, keeping them empty or returning null */
        public X509Certificate[] getAcceptedIssuers() {
            return null;
        }

        public void checkClientTrusted(X509Certificate[] chain, String authType) {

        }

        public void checkServerTrusted(X509Certificate[] chain, String authType) {

        }
    }

    public static class NullHostnameVerifier implements HostnameVerifier {
        public boolean verify(String hostname, SSLSession session) {
            return true;
        }
    }
}
